/*
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *    2011 year
 *    Author: Michael Khromov aka MikeDM (Mike D'Morto)
 *    E-Mail: mikedmorto@gmail.com
 */

#include <Wt/WApplication>
#include <Wt/WEnvironment>
#include <Wt/WLogger>
#include <dlfcn.h>


#include "mcore.h"
#include "ConfigFile.h"

MCore::MCore(const WEnvironment& env)
  : WApplication(env)
{
    // создаем объект для протоколирования.
    this->logger = new MLog(this);
    // пишем в лог сообщение о начале работы приложения
    logger->putlog(L_INFO,"Core","Start");
    // открываем конфиг
    logger->putlog(L_DEBUG,"Core","Open config");
    ConfigFile cfg("upme.ini");
    // читаем из конфига текущий режим работы протоколирования и выставляем этот режим логгеру.
    int cfgloglevel;
    cfg.readInto(cfgloglevel,"loglevel",L_INFO);
    this->logger->setLoglevel(cfgloglevel);
    // берем из конфига значение для редиректа.
    // данная штука используется для редиректа пользователя на спец страницу ошибки
    // если возникла критическая ошибка и продолжать работу приложения невозможно
    // то отобразить ошибку пользователю будет сложно.
    cfg.readInto(this->cfgErrorRedirect,"err_redirect");
    this->logger->putlog(L_DEBUG,"Core","err_redirect="+this->cfgErrorRedirect);
    // подгружаем библиотеку для работы с базой.
    // сначала путь до библиотек выдергиваем из конфига
    cfg.readInto(cfglibpath,"libpath");
    cfg.readInto(cfglibdb,"db");
    // выделяем из строки имя базы данных и ее строку инициализации
    std::string db_plugin=cfglibdb.substr(0,cfglibdb.find_first_of(","));
    std::string db_init=cfglibdb.substr(cfglibdb.find_first_of(",")+1,cfglibdb.size());
    std::string aa(cfglibpath+"/libupme_"+db_plugin+".so"); // fixit переделать под кроссплатформу

    // загружаем библиотеку для работы с бд
    void *handleDB = dlopen(aa.c_str(),RTLD_LAZY);
    if(!handleDB){
        this->logger->putlog(L_INFO,"Core","load database lib "+aa+" failure");
    }else{
        this->logger->putlog(L_INFO,"Core","load database lib "+aa+" success");
        // инициализируем функции
        if(!(this->libDBinit=(bool (*)(const std::string& initstr))dlsym(handleDB,"init"))){
            this->logger->putlog(L_ERROR,"Core","function init not found in database library "+db_plugin);
            // произошла ошибка при работе с библиотекой. продолжать нет смысла. перенаправляем на страницу с ошибкой
            this->redirect(this->cfgErrorRedirect);
        }else{
            this->logger->putlog(L_DEBUG,"Core","function init found in database library "+db_plugin);
        }
        // инициализируем другие фунции бд

        // инициализируем библиотку. тут начинается собственно работа.
        if(this->libDBinit(db_init)){
            this->logger->putlog(L_DEBUG,"Core"," INIT OK");
        }else{
            this->logger->putlog(L_DEBUG,"Core"," INIT FAIL");
        }


    }





/*



    std::string (*mmm)();
    std::string aa(libpath+"/libupme_"+db_plugin+".so");
    void *handle = dlopen(aa.c_str(),RTLD_LAZY);
    if(!handle){
        this->log("error")<<"load lib fail";

    }else{
    if(handle){
        this->log("info")<<"SUCCESS";
        mmm = (std::string(*)())dlsym(handle,"hello");
        this->log("LIB")<<mmm();

        // пробуем работу с либой при возвращении указателя
        std::string *(*fff)();
        fff = (std::string *(*)())dlsym(handle,"LL");
        std::string * af = fff();
        this->log("LINK")<<af->at(0);
        // работает. это значит вери вери гуд.


        dlclose(handle);
    }else{
        this->log("info")<<"ERROR";
    }

    this->log("info")<<"end";
    }



*/
    // запускаем логин

    setTitle("Hello world");                               // application title
    WText * tt = new WText("Hello!");
    tt->setText(tt->text()+this->instance()->appRoot());
    root()->addWidget(tt);
};
